/* **********************************************************************************
 *
 * Copyright (c) Ascend.NET Project. All rights reserved.
 *
 * This source code is subject to terms and conditions of the Shared Source License
 * for Ascend. A copy of the license can be found in the License.html file
 * at the root of this distribution. If you can not locate the Shared Source License
 * for Ascend, please send an email to ascend_adm@hotmail.com.
 * By using this source code in any fashion, you are agreeing to be bound by
 * the terms of the Shared Source License for Ascend.NET.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * **********************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Text;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using Ascend.Resources;

namespace Ascend.Windows.Forms.Design
{
    /// <summary>
    /// Designer class extending the design mode behavior of the NavigationPane.
    /// </summary>
    public class NavigationPaneDesigner : ParentControlDesigner
    {
        private DesignerActionListCollection _actionLists;
        private DesignerVerb _removeVerb;
        private DesignerVerbCollection _verbs;
        private bool _addingOnInitialize;
        private bool _hasFocus;

        /// <summary>
        /// Initializes a new instance of the NavigationPaneDesigner class.
        /// </summary>
        public NavigationPaneDesigner() : base()
        {
        }

        /// <summary>
        /// Gets a value indicating whether selected controls will be re-parented.
        /// </summary>
        protected override bool AllowControlLasso
        {
            get
            {
                return true;

            }

        }

        /// <summary>
        /// Indicates whether the control managed by the specified designer can be a child of the control managed by this designer.
        /// </summary>
        /// <param name="control">The System.Windows.Forms.Control to test.</param>
        /// <returns>
        /// true if the specified control can be a child of the control managed by this designer; otherwise, false.
        /// </returns>
        /// <remarks>
        /// This method indicates whether the control managed by this designer can parent the control of the specified ControlDesigner.
        /// </remarks>
        public override Boolean CanParent(System.Windows.Forms.Control control)
        {
            return (control is NavigationPanePage);

        }

        /// <summary>
        /// Gets the design-time action lists supported by the component associated with the designer.
        /// </summary>
        /// <value>
        /// The design-time action lists supported by the component associated with the designer. 
        /// </value>
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (this._actionLists == null)
                {
                    this._actionLists = new DesignerActionListCollection();
                    this._actionLists.Add(new NavigationPaneActionList((NavigationPane)Control));

                }

                return this._actionLists;

            }

        }

        /// <summary>
        /// Gets or sets a value indicating whether a grid should be drawn on the control for this designer.
        /// </summary>
        /// <value>
        /// Always false in this designer.
        /// </value>
        protected override bool DrawGrid
        {
            get
            {
                return false;

            }

            set
            {
                base.DrawGrid = false;

            }

        }

        /// <summary>
        /// Allows a designer to change or remove items from the set of properties that it exposes through a TypeDescriptor.
        /// </summary>
        /// <param name="properties">The properties for the class of the component.</param>
        protected override void PostFilterProperties(System.Collections.IDictionary properties)
        {
            properties.Remove("BackColor");
            properties.Remove("BackgroundImage");
            properties.Remove("BackgroundImageLayout");
            properties.Remove("AutoScroll");
            properties.Remove("AutoScrollMargin");
            properties.Remove("AutoScrollMinSize");
            properties.Remove("Text");
            properties.Remove("Padding");

            base.PostFilterProperties(properties);

        }

        /// <summary>
        /// Allows a designer to change or remove items from the set of events that it exposes through a TypeDescriptor.
        /// </summary>
        /// <param name="events">The events for the class of the component.</param>
        protected override void PostFilterEvents(System.Collections.IDictionary events)
        {
            events.Remove("BackColorChanged");
            events.Remove("BackgroundImageChanged");
            events.Remove("BackgroundImageLayoutChanged");
            events.Remove("AutoScrollChanged");
            events.Remove("AutoScrollMarginChanged");
            events.Remove("AutoScrollMinSizeChanged");
            events.Remove("TextChanged");

            base.PostFilterEvents(events);

        }

        /// <summary>
        /// Indicates whether a mouse click at the specified point should be handled by the control.
        /// </summary>
        /// <param name="point">A System.Drawing.Point indicating the position at which the mouse was clicked, in screen coordinates.</param>
        /// <returns>true if a click at the specified point is to be handled by the control; otherwise, false.</returns>
        protected override System.Boolean GetHitTest(System.Drawing.Point point)
        {
            if (this._hasFocus)
            {
                Point clientPoint = this.Control.PointToClient(point);
                if (((NavigationPane)this.Control).Render.CaptionRectangle.Contains(clientPoint) || ((NavigationPane)this.Control).Render.FooterRectangle.Contains(clientPoint) || ((NavigationPane)this.Control).Render.FooterConfigureRectangle.Contains(clientPoint))
                {
                    return false;

                }
                else
                {
                    return true;

                }

            }
            else
            {
                return false;

            }

        }

        /// <summary>
        /// Gets or sets the design-time verbs supported by the designer. 
        /// </summary>
        /// <value>
        /// An array of DesignerVerb objects supported by the designer, or null if the component has no verbs.
        /// </value>
        public override DesignerVerbCollection Verbs
        {
            get
            {
                if (this._verbs == null)
                {
                    this._removeVerb = new DesignerVerb(ResourceText.GetLocalizedString("NPRemoveVerbText"), new EventHandler(this.OnRemove));
                    this._verbs = new DesignerVerbCollection();
                    this._verbs.Add(new DesignerVerb(ResourceText.GetLocalizedString("NPAddVerbText"), new EventHandler(this.OnAdd)));
                    this._verbs.Add(this._removeVerb);

                }

                if (this.Control != null)
                {
                    this._removeVerb.Enabled = this.Control.Controls.Count > 0;

                }

                return this._verbs;

            }

        }

        /// <summary>
        /// Receives a call when a drag-and-drop operation is in progress to provide visual cues based on the location of the mouse while a drag operation is in progress.
        /// </summary>
        /// <param name="e">A System.Windows.Forms.GiveFeedbackEventArgs that provides data for the event.</param>
        protected override void OnGiveFeedback(System.Windows.Forms.GiveFeedbackEventArgs e)
        {
            Cursor.Current = Cursors.No;

        }

        /// <summary>
        /// Called when a drag-and-drop object is dragged over the control designer view. 
        /// </summary>
        /// <param name="de">A System.Windows.Forms.DragEventArgs that provides data for the event.</param>
        protected override void OnDragOver(System.Windows.Forms.DragEventArgs de)
        {
            Cursor.Current = Cursors.No;

        }

        /// <param name="de">A System.Windows.Forms.DragEventArgs that provides data for the event.</param>
        protected override void OnDragEnter(System.Windows.Forms.DragEventArgs de)
        {
            ((NavigationPane)this.Control).SelectedNavigationPage.Focus();

        }

        /// <summary>
        /// Fired when the remove verb is selected.
        /// </summary>
        /// <param name="sender">The sending object.</param>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        private void OnRemove(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                NavigationPane control = (NavigationPane)base.Component;
                if ((control == null) || (control.NavigationPages.Count == 0))
                {
                    return;

                }

                MemberDescriptor memberDescriptor = TypeDescriptor.GetProperties(base.Component)["Controls"];
                NavigationPanePage page = control.SelectedNavigationPage;
                IDesignerHost host = (IDesignerHost)this.GetService(typeof(IDesignerHost));
                if (host == null)
                {
                    return;

                }

                DesignerTransaction transaction = null;
                try
                {
                    try
                    {
                        transaction = host.CreateTransaction(ResourceText.GetLocalizedString("NPRemoveVerbText"));
                        base.RaiseComponentChanging(memberDescriptor);

                    }
                    catch (CheckoutException exception)
                    {
                        if (exception != CheckoutException.Canceled)
                        {
                            throw;

                        }

                        return;

                    }

                    control.NavigationPages.Remove(page);
                    host.DestroyComponent(page);
                    base.RaiseComponentChanged(memberDescriptor, null, null);

                }
                catch
                {
                    throw;

                }
                finally
                {
                    if (transaction != null)
                    {
                        transaction.Commit();

                    }

                }

            }
            catch
            {
                throw;

            }
            finally
            {
                Cursor.Current = Cursors.Default;

            }

        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            ISelectionService service = (ISelectionService)this.GetService(typeof(ISelectionService));
            this._hasFocus = false;

            if (service != null)
            {
                ICollection collection = service.GetSelectedComponents();
                NavigationPane navigationPane = (NavigationPane)base.Component;

                foreach (object obj in collection)
                {
                    if (obj == navigationPane)
                    {
                        this._hasFocus = true;

                    }

                    NavigationPanePage navigationPanePage = NavigationPaneDesigner.GetNavigationPanePageOfComponent(obj);
                    if ((navigationPanePage != null) && (navigationPanePage.Parent == navigationPane))
                    {
                        this._hasFocus = false;

                        navigationPane.SelectedNavigationPage = navigationPanePage;
                        //((SelectionManager)this.GetService(typeof(SelectionManager))).Refresh();

                        return;

                    }

                }

            }

        }

        /// <summary>
        /// Fired when the add verb is selected.
        /// </summary>
        /// <param name="sender">The sending object.</param>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        private void OnAdd(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                NavigationPane control = (NavigationPane)base.Component;
                IDesignerHost host = (IDesignerHost)this.GetService(typeof(IDesignerHost));
                if (host == null)
                {
                    return;

                }

                DesignerTransaction transaction = null;
                try
                {
                    try
                    {
                        transaction = host.CreateTransaction(ResourceText.GetLocalizedString("NPAddVerbText"));

                    }
                    catch (CheckoutException exception)
                    {
                        if (exception != CheckoutException.Canceled)
                        {
                            throw;

                        }

                        return;

                    }

                    MemberDescriptor memberDescriptor = TypeDescriptor.GetProperties(control)["Controls"];
                    NavigationPanePage navigationPanePage = (NavigationPanePage)host.CreateComponent(typeof(NavigationPanePage));
                    if (!this._addingOnInitialize)
                    {
                        base.RaiseComponentChanging(memberDescriptor);

                    }

                    string text = null;
                    PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(navigationPanePage)["Name"];
                    if ((propertyDescriptor != null) && (propertyDescriptor.PropertyType == typeof(string)))
                    {
                        text = (string)propertyDescriptor.GetValue(navigationPanePage);

                    }

                    if (text != null)
                    {
                        PropertyDescriptor propertyDescriptorText = TypeDescriptor.GetProperties(navigationPanePage)["Text"];
                        if (propertyDescriptorText != null)
                        {
                            propertyDescriptorText.SetValue(navigationPanePage, text);

                        }
                        
                        PropertyDescriptor propertyDescriptorKey = TypeDescriptor.GetProperties(navigationPanePage)["Key"];
                        if (propertyDescriptorKey != null)
                        {
                            propertyDescriptorKey.SetValue(navigationPanePage, text);

                        }

                    }

                    PropertyDescriptor propertyDescriptorTextAlign = TypeDescriptor.GetProperties(navigationPanePage)["TextAlign"];
                    if (propertyDescriptorTextAlign != null)
                    {
                        propertyDescriptorTextAlign.SetValue(navigationPanePage, control.ButtonTextAlign);

                    }

                    PropertyDescriptor propertyDescriptorImageAlign = TypeDescriptor.GetProperties(navigationPanePage)["ImageAlign"];
                    if (propertyDescriptorImageAlign != null)
                    {
                        propertyDescriptorImageAlign.SetValue(navigationPanePage, control.ButtonImageAlign);

                    }

                    PropertyDescriptor propertyDescriptorButtonForeColor = TypeDescriptor.GetProperties(navigationPanePage)["ButtonForeColor"];
                    if (propertyDescriptorButtonForeColor != null)
                    {
                        propertyDescriptorButtonForeColor.SetValue(navigationPanePage, control.ButtonForeColor);

                    }

                    PropertyDescriptor propertyDescriptorGradientHighColor = TypeDescriptor.GetProperties(navigationPanePage)["GradientHighColor"];
                    if (propertyDescriptorGradientHighColor != null)
                    {
                        propertyDescriptorGradientHighColor.SetValue(navigationPanePage, control.ButtonGradientHighColor);

                    }

                    PropertyDescriptor propertyDescriptorGradientLowColor = TypeDescriptor.GetProperties(navigationPanePage)["GradientLowColor"];
                    if (propertyDescriptorGradientLowColor != null)
                    {
                        propertyDescriptorGradientLowColor.SetValue(navigationPanePage, control.ButtonGradientLowColor);

                    }

                    PropertyDescriptor propertyDescriptorActiveGradientHighColor = TypeDescriptor.GetProperties(navigationPanePage)["ActiveGradientHighColor"];
                    if (propertyDescriptorActiveGradientHighColor != null)
                    {
                        propertyDescriptorActiveGradientHighColor.SetValue(navigationPanePage, control.ButtonActiveGradientHighColor);

                    }

                    PropertyDescriptor propertyDescriptorActiveGradientLowColor = TypeDescriptor.GetProperties(navigationPanePage)["ActiveGradientLowColor"];
                    if (propertyDescriptorActiveGradientLowColor != null)
                    {
                        propertyDescriptorActiveGradientLowColor.SetValue(navigationPanePage, control.ButtonActiveGradientLowColor);

                    }

                    PropertyDescriptor propertyDescriptorHighlightGradientHighColor = TypeDescriptor.GetProperties(navigationPanePage)["HighlightGradientHighColor"];
                    if (propertyDescriptorHighlightGradientHighColor != null)
                    {
                        propertyDescriptorHighlightGradientHighColor.SetValue(navigationPanePage, control.ButtonHighlightGradientHighColor);

                    }

                    PropertyDescriptor propertyDescriptorHighlightGradientLowColor = TypeDescriptor.GetProperties(navigationPanePage)["HighlightGradientLowColor"];
                    if (propertyDescriptorHighlightGradientLowColor != null)
                    {
                        propertyDescriptorHighlightGradientLowColor.SetValue(navigationPanePage, control.ButtonHighlightGradientLowColor);

                    }

                    PropertyDescriptor propertyDescriptorPaneButtonFont = TypeDescriptor.GetProperties(navigationPanePage)["ButtonFont"];
                    if (propertyDescriptorPaneButtonFont != null)
                    {
                        propertyDescriptorPaneButtonFont.SetValue(navigationPanePage, new Font(control.Font.FontFamily, 8.25f, FontStyle.Bold));

                    }

                    PropertyDescriptor propertyDescriptorCaptionFont = TypeDescriptor.GetProperties(control)["CaptionFont"];
                    if (propertyDescriptorCaptionFont != null)
                    {
                        propertyDescriptorCaptionFont.SetValue(control, new Font(control.Font.FontFamily, 11.25f, FontStyle.Bold));

                    }

                    PropertyDescriptor propertyDescriptorButtonFont = TypeDescriptor.GetProperties(control)["ButtonFont"];
                    if (propertyDescriptorButtonFont != null)
                    {
                        propertyDescriptorButtonFont.SetValue(control, new Font(control.Font.FontFamily, 8.25f, FontStyle.Bold));

                    }

                    if (control.NavigationPages != null)
                    {
                        control.NavigationPages.Add(navigationPanePage);
                        if (!this._addingOnInitialize)
                        {
                            base.RaiseComponentChanged(memberDescriptor, null, null);

                        }

                    }

                }
                catch
                {
                    throw;

                }
                finally
                {
                    if (transaction != null)
                    {
                        transaction.Commit();

                    }

                }

            }
            catch
            {
                throw;

            }
            finally
            {
                Cursor.Current = Cursors.Default;

            }

        }

        /// <summary>
        /// Initializes a newly created component.
        /// </summary>
        /// <param name="defaultValues">A name/value dictionary of default values to apply to properties. May be null if no default values are specified.</param>
        public override void InitializeNewComponent(System.Collections.IDictionary defaultValues)
        {
            base.InitializeNewComponent(defaultValues);

            try
            {
                this._addingOnInitialize = true;
                this.OnAdd(this, EventArgs.Empty);

            }
            finally
            {
                this._addingOnInitialize = false;

            }

            MemberDescriptor memberDescriptor = TypeDescriptor.GetProperties(base.Component)["Controls"];
            base.RaiseComponentChanging(memberDescriptor);
            base.RaiseComponentChanged(memberDescriptor, null, null);
            NavigationPane control = (NavigationPane)base.Component;
            if (control != null)
            {
                control.SelectedIndex = 0;

            }

        }

        /// <summary>
        /// Initializes the designer with the specified component.
        /// </summary>
        /// <param name="component">The IComponent to associate the designer with. This component must always be an instance of, or derive from, Control.</param>
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);

            ISelectionService service = (ISelectionService)this.GetService(typeof(ISelectionService));
            if (service != null)
            {
                service.SelectionChanged += new EventHandler(this.OnSelectionChanged);

            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ISelectionService service = (ISelectionService)this.GetService(typeof(ISelectionService));
                if (service != null)
                {
                    service.SelectionChanged -= new EventHandler(this.OnSelectionChanged);

                }

            }

            base.Dispose(disposing);

        }

        /// <summary>
        /// Returns the navigationpane page of the passed component.
        /// </summary>
        /// <param name="component"></param>
        /// <returns></returns>
        internal static NavigationPanePage GetNavigationPanePageOfComponent(object component)
        {
            if (!(component is Control))
            {
                return null;

            }

            Control control = (Control)component;
            while ((control != null) && !(control is NavigationPanePage))
            {
                control = control.Parent;

            }

            return (NavigationPanePage)control;

        }

    }

}
